//
//  ScannerManager.swift
//  ezyform
//
//  Created by Moennig Q on 10/10/2022.
//  Copyright © 2022 Client.Solution Pty Ltd. All rights reserved.
//

import Foundation
import DynamsoftBarcodeReader
import DynamsoftCameraEnhancer
class ScannerManager: NSObject, DBRLicenseVerificationListener{
    static let shared = ScannerManager()
    var dceView: DCECameraView!
    var barcodeReader: DynamsoftBarcodeReader!
    var dce: DynamsoftCameraEnhancer!
    func initLicense(){
        if !UIDevice.isSimulator{//不是虚拟器才初始化
            DynamsoftBarcodeReader.initLicense(APPConfig.ScannerLicense, verificationDelegate: self)
        }
    }
    func dbrLicenseVerificationCallback(_ isSuccess: Bool, error: Error?) {
        if isSuccess {
            APPConfig.ScannerLicenseValidFlag = true
            DebugLog("license有效")
            //证书有效就初始化scanner
            self.prepareScanner()
        }else{
            APPConfig.ScannerLicenseValidFlag = false
            if let err = error as? NSError,let msg = err.userInfo[NSUnderlyingErrorKey] as? String {
                DebugLog(msg)
                SentryHelper().captureCustomLog(msg)//发送license无效的信息到sentry
            }
        }
    }
    func prepareScanner(){
        if APPConfig.ScannerLicenseValidFlag {
            self.configurationDBR()
            self.configurationDCE()
            DebugLog("dce 初始化完毕")
            //MARK: - 只有测试有
            self.setLocalLogOnlyForTest()
        }
    }
    
    func pauseScanner() {
        //不要试图调用dispose接口，解码线程与调用dispose接口不在同一线程的话，因此如果先dispose释放了内部的dbr对象，解码线程还在使用dbr对象就会导致崩溃。
        
        //dispose只有自己调用解码接口，能确保再同一线程同步执行才可以调用，不然就会导致崩溃
        //dispose接口释放的是内部的dbr指针，如果不需要使用ios的dbr对象，只需要barcodeReader = nil，我们会在ios dbr对象释放时候释放内部的dbr指针
//      //barcodeReader.dispose()
        self.barcodeReader?.stopScanning()
        self.dce?.close()
        DebugLog("第三方Scanner destroy")
    }
    private func configurationDBR() {
        if barcodeReader == nil{
            barcodeReader = DynamsoftBarcodeReader.init()
            barcodeReader.updateRuntimeSettings(EnumPresetTemplate.videoSingleBarcode)
            if let settings = try? barcodeReader.getRuntimeSettings(){
                //ios的摄像头拍摄的图片需要逆时针转90度才是屏幕上看到的图片的样子,所以region中的参数left，right代表实际的top，bottom，
                //region中的参数top，bottom代表实际的left，right
                settings.region.regionTop = 0
                //3.2.1版本使用的是7.3版本扫描区域从扫描框大小改成从屏幕顶部到扫描框的底部，左右没有变化，解决扫描barcode部分条形码的时候，扫描线偏离正确位置的问题
                //3.3.0使用新的扫码库7.4.0版本（此版本纠正了容易扫出乱码的问题），扫描区域再设置成扫描框大小，没有初夏扫描线偏离的情况了
                settings.region.regionLeft = Int(APPConfig.scanViewTopMargin / UIScreen.main.bounds.height * 100)
                settings.region.regionRight = Int((APPConfig.scanViewTopMargin + APPConfig.scanViewHeight) / UIScreen.main.bounds.height * 100)
                settings.region.regionBottom = 100
                //1 代表百分比，0是具体的坐标值可
                settings.region.regionMeasuredByPercentage = 1
                //2.可信度
                settings.minResultConfidence = APPConfig.ScannerConfidence
                //设置LM_ONED_FAST_SCAN，开启一维码加快扫描速度的开关
                //localizationModes中有8中模式选择，可以组合配置，配置选项的链接是：https://www.dynamsoft.com/barcode-reader/parameters/enum/parameter-mode-enums.html#localizationmode
                //settings.localizationModes = [0, 0, 0, 0, 0,2, 100, 8 ]这样写是一样的，越靠前的模式优先使用。其他Mode设置类似
                settings.localizationModes = [EnumLocalizationMode.connectedBlocks.rawValue, EnumLocalizationMode.oneDFastScan.rawValue, EnumLocalizationMode.lines.rawValue, 0, 0, 0, 0, 0 ]
                //3.对比前后帧的码结果再将结果返回。如果设为true，我们SDK会对比前后两次返回的码结果，如果结果一致，才会输出
                barcodeReader.enableResultVerification = true
                //5.设置识别间隔
//                barcodeReader.minImageReadingInterval = 500//取消设置此属性，因为影响识别速度
                //7.设置解码最大线程数为1，减少手机发烫的问题
                settings.maxAlgorithmThreadCount = 1
                //9. barcodeFormatIds和barcodeFormatIds_2是两个format组，barcodeFormatIds_2是不常用的，所以设置为null
                settings.barcodeFormatIds_2 = EnumBarcodeFormat2.Null.rawValue
                try? barcodeReader.updateRuntimeSettings(settings)
                //打印当下的扫描配置
//                self.printScannerSetting()
            }
        }
    }
    // MARK: - 初始化DCE
    private func configurationDCE() {
        if dce == nil {
            //Initialize a camera view for previewing video.
            self.dceView = DCECameraView.init(frame: CGRect(x: 0, y: 0, width: APPConfig.WidthForPortrait, height: APPConfig.HeightForPortrait))
            //将预览层dceView加载到view上
//            self.addSubview(self.dceView)
            // Initialize the Camera Enhancer with the camera view.
            dce = DynamsoftCameraEnhancer.init(view: dceView)
//            dce.open()
            // Bind Camera Enhancer to the Barcode Reader.
            // The Barcode Reader will get video frame from the Camera Enhancer
            barcodeReader.setCameraEnhancer(dce)

            // Set text result call back to get barcode results.
//            barcodeReader.setDBRTextResultListener(self)
        }
    }
    // MARK: - 初始化DBR
    private func setLocalLogOnlyForTest(){
//        if APPConfig.isTestFlag {
//            let dPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].path + "/"
//            do{
//                try DynamsoftBarcodeReader.setLogConfig(dPath)//.setLogConfig(dPath, mode: .LM_TEXT)
//            }catch{
//                DebugLog("DynamsoftBarcodeReader.setLogConfig(dPath, mode: .LM_TEXT) failed")
//            }
//        }
    }
}
